﻿module TopDown_LL0_Parser
//open System
//open Ast
//
//type Parser<'a> = string -> ('a * string) option
//
////////////////haskell style funzionante//////
///////////////////////////////////////////////
////
////let (>>=) p k : Parser<'a> =
////  fun s -> 
////    match p s with
////    None -> None
////    | Some (x,s') -> (k x) s'
////
////let Result x : Parser<'a> = fun s -> Some (x, s)
////
////let item =  
////  fun s ->
////    match s with
////    | "" -> None
////    | s -> Some (s.[0], s.Substring(1))
////
////let firstTwoItems =
////  item >>= (fun s1 ->
////  item >>= (fun s2 ->
////  Result (sprintf "%c%c" s1 s2)))
///////////////////////////////////////////////
///////////////////////////////////////////////
//
//
//type ParserBuilder() =
//  member this.Return(x:'a) : Parser<'a> = 
//    fun s -> Some (x,s)
//  member this.Bind(p:Parser<'a>, k : 'a -> Parser<'b>) : Parser<'b> =
//    fun s -> 
//      match p s with
//      None -> None
//      | Some (x, s') -> (k x) s'
//  member this.Combine(p:Parser<'a>, k : Parser<'b>) : Parser<'b> =
//    this.Bind(p, fun _ -> k)
//
//  //membri interni necessari per la gestione e la creazione della monade
//  member this.Delay s = this.Bind(this.Return(), s)
//  member this.Run s = s
//  member this.Zero () = fun s -> None
//  member this.ReturnFrom p = p  
//
//let parser = ParserBuilder()
//
//let fail : Parser<'a> = fun s -> None
//
//let item : Parser<char> = 
//  fun s ->
//    match s with
//    | "" -> None
//    | s -> Some (s.[0], s.Substring(1))
//
//let parse (p:Parser<'a>) s = p s
//
//let sat p =
//  parser{
//    let! s = item
//    if p s then 
//      return s
//  }
//
//let get_state : Parser<string> =
//  fun s -> Some(s,s)
//
//let lift_1 f s1 =
//  parser{
//    let! x1 = s1
//    return f x1
//  }
//
//let ignore_ s = lift_1 (fun x -> ()) s
//let digit = sat Char.IsDigit
//let lower = sat Char.IsLower
//let isSpace = fun c -> c = ' '
//
//let return_ s = parser{ return s }
//
//let v (p : Parser<'a>) (q : Parser<'a>) : Parser<'a> = 
//  fun s ->
//    match p s with
//    None -> q s
//    | res -> res
//
//let rec many p =
//  v (many1 p) (return_ "")
//
//and many1 p =
//  parser{
//    let! x = sat p
//    let! xs = many p
//    return (string x) + xs
//  }
//
//and spaces =
//  parser{
//    do! many isSpace |> ignore_
//  }
//
//
//let char x = sat ((=) x)
//
//let token p =
//  parser{
//    do! spaces
//    let! v = p
//    do! spaces
//    return v
//  }
//
//let rec string s =
//  parser{
//    if s = "" then return ()
//    else
//      let x, xs = s.[0], s.Substring(1)
//      do! char x |> ignore_
//      do! string xs
//  }
//
//let symbol s = token (string s)
//
//let comma =
//  parser{
//    do! symbol ","
//  }
//let semicolon =
//  parser{
//    do! symbol ";"
//  }
//
//let rec parse_list _parser =   
//  parser{
//    return!
//      v (parser{
//            let! head = _parser
//            let! tail = parse_list _parser
//            return (head :: tail)
//            })
//        (parser{ return [] })
//  }
//
//let rec parse_list_with_pred _parser pred =
//  parser{
//    return!
//      v (parser{
//            do! pred
//            return!
//              v (parser{
//                    let! head = _parser
//                    let! tail = parse_list_with_pred _parser pred
//                    return (head :: tail)
//                    })
//                (parser{ return [] })
//          })
//        (parser{ return [] })
//  }
//
//let parse_list_first_without_pred _parser pred =    
//  parser{
//    return!
//      v (parser{
//            let! head = _parser
//            let! tail = parse_list_with_pred _parser pred
//            return (head :: tail)
//            })
//        (parser{ return [] })
//  }
//
//
//let nat =
//  parser{
//    let! n = many1 Char.IsDigit
//    return Int32.Parse(n)
//  }
//
//let ureal =
//  parser{
//    let! n = many1 Char.IsDigit
//    do! symbol "."
//    let! r = many1 Char.IsDigit
//    return float (n + "." + r)
//  }
//
//let idbody =
//  parser{
//    do! spaces
//    let! body = many1 ((fun c_list c -> 
//                          [for c' in c_list -> c' <> c] |> Seq.exists(fun res -> res = false) |> not)
//                        [' '; ';';'(';'[';')';']';',';'{';'}'])
//    return body
//  }
//
//let Uid =
//  parser{
//    let! Ufirst = sat Char.IsUpper
//    let! even = idbody
//    return (sprintf "%c%s" Ufirst even)
//  }
//
//let Lid =
//  parser{
//    let! Lfirst = sat Char.IsLower
//    let! even = idbody
//    return (sprintf "%c%s" Lfirst even)
//  }
//
//let newline = 
//  parser{
//    do! v (symbol "\n") (symbol "\r\n")
//  }
//
//let rec many_v v_list =
//  match v_list with
//  |[] -> fail
//  | [x] -> v x fail
//  | x::xs -> v x (many_v xs)
//
//let rec comment =
//  parser{
//    let! res =
//      v (parser{
//          do! v (symbol "*)") (symbol "*/")
//         })
//        (parser{
//          do! item |> ignore_
//          do! comment
//        })
//    return res
//  }
//
//and linecomment =
//  parser{
//    let! res =
//      v (parser{
//            do! newline
//           })
//          (parser{
//            do! item |> ignore_
//            let! res = linecomment
//            return res
//          })
//    return res
//  }
//
//
//let rec stmt : Parser<Stmt> =
//  parser{
//    let tokens =
//      [ parser{
//          let! assign = assign
//          do! symbol ";"
//          return Stmt.Assign assign
//        };
//        parser{
//          let! call = call
//          do! symbol ";"
//          return Stmt.Call call
//        };
//        parser{
//          let! return_ = 
//            let tokens =
//              [(parser{
//                  do! symbol "return"
//                  do! symbol ";"
//                  return None
//                });
//                (parser{
//                  do! symbol "return"
//                  let! expr = expr
//                  do! symbol ";"
//                  return Some expr  
//                });
//                (parser{ return None})]
//            many_v tokens
//          return Return return_
//        };
//        parser{
//          do! symbol "if"
//          do! symbol "("
//          let! expr = expr
//          do! symbol ")"
//          do! symbol "{"
//          let! stmt1 = stmt
//          do! symbol "}"
//          let! stmt_option = 
//            v (parser{
//                do! symbol "else"
//                do! symbol "{"
//                let! stmt_option = stmt
//                do! symbol "}"
//                return Some stmt_option 
//              })
//              (parser{ return None})
//          return If(expr, stmt1, stmt_option)
//        };
//        parser{
//          do! symbol "while"
//          do! symbol "("
//          let! expr = expr
//          do! symbol ")"
//          do! symbol "{"
//          let! stmt = stmt
//          do! symbol "}"
//          return While(expr,stmt)
//        };
//        parser{
//          do! symbol "break"
//          do! symbol ";"
//          return Break
//        };
//        parser{
//          do! symbol "continue"
//          do! symbol ";"
//          return Continue };
//        parser{
//          let! block = block
//          return Stmt.Block block };]
//    return! many_v tokens
//  }
//and assign : Parser<Assign> =
//  parser{
//    let! location = location
//    do! symbol "="
//    let! expr = expr
//    return Assign(location, expr)
//  }
//and method_ =
//  parser{
//    let tokens =
//      [ parser{
//          let! id = id
//          return Method id 
//        };
//        parser{
//          let! expr = expr
//          do! symbol "."
//          let! id = id
//          return Select(expr,id)
//        }]
//    return! many_v tokens
//  }
//and actuals : Parser<Actuals> =
//  parser{
//    let! expr1 = expr
//    let! k = get_state
//
//    let rec expr_list k =
//      match parse expr k with
//      | None -> []
//      |Some(expr,k) -> 
//        expr :: (expr_list k)
//
//    let expr_list = expr_list k
//    return Actuals(expr1, expr_list)
//  }
//and call : Parser<Call> =
//  parser{
//    let! method_ = method_
//    do! symbol "("
//    let! actuals =
//      v (parser{
//          let! actuals = actuals
//          return Some actuals})
//        (parser{
//          return None})
//    return Call.Call(method_, actuals)
//  }
//and expr : Parser<Expr> =
//  parser{
//    let tokens =
//      [ parser{
//          let! location = location
//          return Location location
//        };
//        parser{
//          let! call = call
//          return Call call
//        };
//        parser{
//          do! symbol "new"
//          let! id = id
//          return New id
//        };
//        parser{
//          do! symbol "new"
//          let! array_type = type_ 
//          do! symbol "["
//          let! expr = expr
//          do! symbol "]"
//          return NewArray (array_type, expr)
//        };
//        parser{
//          let! expr = expr
//          do! symbol "."
//          do! symbol "length"
//          return Length expr
//        };
//        parser{
//          let! expr1 = expr
//          let! binary = binary
//          let! expr2 = expr
//          return Binary (expr1, binary, expr2)
//        };
//        parser{
//          let! unary = unary
//          let! expr = expr
//          return Unary (unary, expr)
//        };
//        parser{
//          let! literal = literal
//          return Literal literal
//        };
//        parser{
//          do! symbol "("
//          let! expr = expr
//          do! symbol ")"
//          return Bracket expr
//        };
//        parser{
//          do! symbol "this"
//          return This
//        };]
//    return! many_v tokens
//  }
//
//and location : Parser<Location> =
//  parser{
//    let tokens =
//      [parser{
//        let! id = id
//        return Id id
//       };
//       parser{
//        let! expr = expr
//        do! symbol "."
//        let! id = id
//        return Member (expr,id)
//       };
//       parser{
//        let! expr1 = expr
//        do! symbol "["
//        let! expr2 = expr
//        do! symbol "]"
//        return Nth (expr1,expr2)
//       }]
//
//    return! many_v tokens
//  }
//
//and type_ : Parser<Type> =
//  parser{
//    let tokens=
//      [ (parser{ do! symbol "bool"
//                 return Boolean});
//
//        (parser{ do! symbol "Int"
//                 return Integer});
//
//        (parser{ do! symbol "String"
//                 return String });
//
//        (parser{ 
//                   let! tp = type_ 
//                   do! symbol "["
//                   do! symbol "]"
//                   return Array tp });
//
//        (parser{ let! body = idbody
//                 return Identifier });]
//
//    return! many_v tokens
//  }
//
//and id : Parser<id> =
//  parser{ let! body = idbody
//          return body 
//  }
//
//and binary : Parser<Binary> =
//  parser{
//    let tokens =
//      [(parser{
//          do! symbol "+"
//          return Sum
//        });
//       (parser{
//          do! symbol "-"
//          return Minus
//        });
//       (parser{
//          do! symbol "*"
//          return Mul
//        });
//        (parser{
//          do! symbol "\\"
//          return Div
//        });
//        (parser{
//          do! symbol "|"
//          return Or
//        });
//        (parser{
//          do! symbol "&"
//          return And
//        });
//        (parser{
//          do! symbol "<"
//          return Min
//        });
//        (parser{
//          do! symbol "<="
//          return MinEq
//        });
//        (parser{
//          do! symbol ">"
//          return Greater
//        });
//        (parser{
//          do! symbol ">="
//          return GreaterEq
//        });
//        (parser{
//          do! symbol "=="
//          return Eq
//        });
//        (parser{
//          do! symbol "!="
//          return NotEq
//        })]
//    return! many_v tokens
//  }
//
//and unary : Parser<Unary> =
//  parser{
//    return!
//      v (parser{ do! symbol "-"
//                 return Negative })
//        (parser{ do! symbol "!"
//                 return Not })
//  }
//
//and literal : Parser<Literal> =
//  parser{
//    let tokens=
//      [(parser{ let! nat = nat
//                return Int nat });
//
//        (parser{ do! symbol "\""
//                 let! body = many1 ((<>) '\"')       
//                 return Str body });
//
//        (parser{ do! symbol "true"
//                 return Bool true });
//
//        (parser{ do! symbol "false"
//                 return Bool true });
//
//        (parser{ do! symbol "null"
//                 return Null })]
//
//    return! many_v tokens
//  }
//and return_type : Parser<ReturnType> =
//  parser{
//    let! return_type =
//      v (parser{
//          let! void_ = symbol "void"
//          return Void
//        })
//        (parser{
//          let! type_ = type_ 
//          return Type type_
//        })
//    return return_type
//  }
//
//
//and vardecl : Parser<VarDecl> =
//  parser{
//    let! type_ = type_ 
//    let! id1 = id
//    let! stmt_opt =
//      v (parser{
//          do! symbol "="
//          let! expr = expr
//          return (Some expr)
//        })
//        (parser{
//          return None
//        })
//    let! id_expr =
//      v (parser{
//          do! symbol ";"
//          return []
//        })
//        (parser{
//            let id_expr =
//              parser{
//                let! id = id
//                do! symbol "="
//                let! expr = expr
//                return (id,expr)
//              }
//            let! res = (parse_list_with_pred id_expr comma)
//            do! symbol ";"
//            return res
//          })
//    return VarDecl.VarDecl(type_, id1, stmt_opt,id_expr)
//  }
//and block : Parser<Block> =
//  parser{
//    do! symbol "{"
//    let! k = get_state
//    let! vardecl_lst = parse_list vardecl
//    let! stmt_lst = parse_list stmt
//    do! symbol "}"
//    return Block.Block(vardecl_lst, stmt_lst)
//  }
//
//and program : Parser<Program> =
//  parser{
//    let! classdecl = parse_list class_decl
//    return ClassDecl classdecl
//  }
//and class_decl : Parser<ClassDecl> =
//  parser{
//    do! symbol "class"
//    let! _id = id
//
//    let! extends_id =
//      let tokens = 
//        [(parser{
//            do! symbol "extends"                
//            let! id = id
//            return Some id
//          });
//          (parser{                         
//            return None
//          })]
//      many_v tokens
//    do! symbol "{"
//    let! fieldOrMethodDecls = parse_list fieldOrMethodDecl
//    do! symbol "}"
//    return ClassDecl.Class(_id, extends_id, fieldOrMethodDecls)
//  }
//and fieldOrMethodDecl : Parser<FieldOrMethodDecl> =
//  parser{
//    return!
//      v (parser{
//          let! fieldDecl = fieldDecl
//          return FieldOrMethodDecl.FieldDecl(fieldDecl)
//        })
//        (parser{
//          let! methDecl = methDecl
//          return FieldOrMethodDecl.MethodDecl(methDecl)
//        })
//  }
//
//and fieldDecl : Parser<FieldDecl> =
//  parser{
//    let! type_ = type_ 
//    let! id_ = id
//    let! id_list = parse_list id
//    do! symbol ";"
//    return FieldDecl(type_, id_, id_list)
//  }
//and methDecl : Parser<MethodDecl> =
//  parser{
//    let! return_type = return_type
//    let! id = id
//    do! symbol "("
//    let! args = parse_list_first_without_pred arg comma
//    do! symbol ")"
//    let! block = block
//    return MethodDecl(return_type, id, args, block)
//  }
//and arg : Parser<Arg> =
//  parser{
//    let! type_ = type_ 
//    let! id = id
//    return Arg(type_, id)
//  }
//
